package com.beiding.config;

import com.beiding.timeout.bean.DelayTaskExecutor;
import com.beiding.timeout.bean.DelayTaskListener;
import com.beiding.timeout.bean.DelayTaskPersistence;
import com.beiding.timeout.bean.TimeShaft;
import com.beiding.timeout.dao.*;
import com.beiding.utils.AmqpUtils;
import com.beiding.utils.LogUtils;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

@Configuration
public class DelayTaskConfig {

    //时间轴仓库
    @Bean
    public TimeShaftDao<String> timeShaftDao(TasksMap<String> tasksMap, TaskIndexMap taskIndexMap, TimeShaftDescription timeShaftDescription, TaskMarkerSortedSet taskMarkerSortedSet) {
        return new TimeShaftDaoImpl<>(timeShaftDescription, taskMarkerSortedSet, taskIndexMap, tasksMap);
    }


    private TimeShaft<String> timeShaft;

    @Autowired
    public void setTimeShaft(TimeShaft<String> timeShaft) {
        this.timeShaft = timeShaft;
    }

    //延时任务执行器
    @Bean
    public DelayTaskExecutor<String> delayTaskExecutor(List<DelayTaskListener<String>> list) {
        DelayTaskExecutor<String> executor = new DelayTaskExecutor<String>() {
            @Override
            protected void onError(Exception e) {
                LogUtils.info(this.getClass(), e);
            }

            @Override
            protected void onNoSuchListener(DelayTaskPersistence<String> persistence) {
                timeShaft.invalidate(persistence.getId());
                LogUtils.error(this.getClass(), "没有执行" + persistence.getType() + "类型的监听器.已将其失效");
            }

            @Override
            protected void onSuccess(DelayTaskPersistence persistence) {
                timeShaft.invalidate(persistence.getId());
            }
        };
        executor.addListeners(list);
        return executor;
    }

    private RabbitTemplate rabbitTemplate;

    @Autowired
    public void setRabbitTemplate(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }


    private TimeShaftDao<String> timeShaftDao;

    @Autowired
    public void setTimeShaftDao(TimeShaftDao<String> timeShaftDao) {
        this.timeShaftDao = timeShaftDao;
    }

    //派发任务队列
    @Bean
    public Queue taskDistributeQueue() {
        return AmqpUtils.createQueue("order.task.distribute.event");
    }


    //监听派发任务事件
    @RabbitListener(queues = "order.task.distribute.event")
    public void onTaskDistributeQueue(Long time) {
        timeShaftDao.getTasks(time).forEach(stringDelayTaskPersistence -> {

            //发送执行任务的消息
            rabbitTemplate.convertAndSend("order.task.execute.event", stringDelayTaskPersistence);
        });
    }

    //时间轴对象
    @Bean
    public TimeShaft<String> timeShaft(TimeShaftDao<String> timeShaftDao, RabbitTemplate rabbitTemplate) {

        return new TimeShaft<>(timeShaftDao, 1000, 20 * 1000, occurTime -> {

            //发出派发消息的事件
            rabbitTemplate.convertAndSend("order.task.distribute.event", occurTime);
        });
    }

    private DelayTaskExecutor<String> executor;

    @Autowired
    public void setExecutor(DelayTaskExecutor<String> executor) {
        this.executor = executor;
    }

    //任务执行队列
    @Bean
    public Queue taskExecuteQueue() {
        return AmqpUtils.createQueue("order.task.execute.event");
    }

    @RabbitListener(queues = "order.task.execute.event")
    public void exe(DelayTaskPersistence<String> stringDelayTaskPersistence) {
        executor.execute(stringDelayTaskPersistence);
    }


}
